/** Animated TreeMenu script by Garrett Smith
*
*  - Evaluation Edition -
*  Not Registered
*
*  email:admin@dhtmlkitchen.com
*
*  Usage: http://dhtmlkitchen.com/
*  Last Modified [01/16/04]
*/

function toggleMenu(el) {
	
	if(Browser.OP5 || Browser.NS4) return; 
	
	var l = Button.getLabel(el);
	
	
	if(l.isDepressed) {
		if (TreeParams.OPEN_MULTIPLE_MENUS || l.menu.container.activeMenu == l.menu) {
			
			l.menu.closeStart();
			l.menu.container.activeMenu = null;
			
		}
	}
	else { // push it in.
		
		if(TreeParams.OPEN_MULTIPLE_MENUS || l.menu.container.activeMenu == null ) {
			l.menu.openStart();
			l.menu.container.activeMenu = l.menu;
		}
		else {
			l.menu.container.activeMenu.closeStart();


		// Cue up this menu to the active menu 
			if(!TreeParams.OPEN_WHILE_CLOSING) {
			
			 // l may be closing and un-depressed.
				if(l.menu.container.activeMenu != l.menu)
 					l.menu.container.activeMenu.menuInCue = l.menu;
 					
 				else { // trying to re-open active menu before it has closed.
 					l.menu.menuInCue = null;
 					l.menu.openStart();
 				}
 					
			}
			else {
				l.menu.openStart();
				l.menu.container.activeMenu = l.menu;
			}

 		}
	}
}

/** Opens a menu.
 *  Usually called with body onload handler.
 */
function activateMenu(sButtonId) { 
	
	if(!window.toggleMenu || Browser.OP5)
		return;
		
	var b = document.getElementById(sButtonId);
	
	if(!b) return;
	
	var parentMenuEl = findAncestorWithClass(b, "menu");
	if(parentMenuEl != null)
		activateMenu(parentMenuEl.id.replace(/Menu$/,""));
	
	var l = Button.getLabel(getElementsWithClass(b, "span", "buttonlabel")[0]);
	if(!l.isDepressed){
		toggleMenu(l.el);
		l.isDepressed = true;
	}
}

function deactivateMenu(sButtonId) {
	if(!window.toggleMenu || Browser.OP5)
		return;
		
	var b = document.getElementById(sButtonId);
	
	if(!b) return;
	
	var l = Button.getLabel(getElementsWithClass(b, "span", "buttonlabel")[0]);
	if(l.isDepressed){
		toggleMenu(l.el);
		l.isDepressed = false;
	}
}

function openTree(sTreeId) {
	if(!TreeParams.OPEN_MULTIPLE_MENUS) return;
	var tree = TreeList[sTreeId];
	var btns = getElementsWithClass(tree.el, "div", "button");
	for(var i = 0, len = btns.length; i < len; i++)
		activateMenu(btns[i].id);
}

function closeTree(sTreeId, defaultButtonId) {
	var tree = TreeList[sTreeId];
	var btns = getElementsWithClass(tree.el, "div", "button");
	for(var i = 0, len = btns.length; i < len; i++) {
		if(btns[i].id != defaultButtonId && 
		  ! getDescendantById(document.getElementById(btns[i].id+"Menu"), defaultButtonId))
			deactivateMenu(btns[i].id);	
	}
}

/** Button mouseover event handler.
 *  Called with onmouseover attribute.
 */
function buttonOver(el){
	
	window.status = el.parentNode.id;
	
	l = Button.getLabel(el);
	l.hasMouseOver = true;
	if(hasToken(l.el.className, "labelHover"))
		return;
	if(l.icn != null)
		l.icn.src = l.isDepressed ? l.icn_do.src : l.icn_o.src;
	
	l.el.className += " labelHover";
}

/** Button mouseout event handler.
 */
function buttonOff(el){
	window.status = window.defaultStatus;
	var l = Button.getLabel(el);
	l.hasMouseOver = false;
	if(l.icn != null)
		l.icn.src = l.isDepressed ? l.icn_d.src : l.origSrc;
		
	removeClass(l.el, "labelHover");
}

if(typeof document.getElementsByTagName == "undefined" || Browser.OP5)
	buttonOver = buttonOff = function(){};


/** Button constructor to be used privately.
 *  A button's icon may be unique or global.
 */
Button = function(el, category){
	
	this.el = el;
	
	if(typeof el.style.MozUserSelect == "string")
		el.style.MozUserSelect = "none";
	else 
		el.onselectstart = function(){ return false; };
		
	this.category = category;
	this.menu = new Menu(document.getElementById(this.category +"Menu"), this);	

	var icns = el.getElementsByTagName("img");
	this.icn = (icns.length > 0) ? icns[0] : null;
	this.hasMouseOver = false;
	
	if(this.icn != null) {
	
		this.origSrc = this.icn.src;
		
		var tp = TreeParams;
		var idv = tp.ICON_TYPE_INDIVIDUAL;
		var ext = tp.IMG_EXT, src = this.origSrc;
		
		this.icn_o = new Image();
		this.icn_o.src = !idv ? tp.CLOSED_OVER_MENU_ICON : src.replace(TokenizedExps.EXT, ext.OVER+"$1");
		this.icn_d = new Image();
		this.icn_d.src = !idv ? tp.OPEN_MENU_ICON : src.replace(TokenizedExps.EXT, ext.DOWN+"$1");
		this.icn_do = new Image();
		this.icn_do.src = !idv ? tp.OPEN_OVER_MENU_ICON : src.replace(TokenizedExps.EXT, ext.DOWN_OVER+"$1");
	}
	
	this.isIcon = false;
	if(el.tagName.toLowerCase() == "img"){
		this.isIcon = true;
		this.icn = el;
	}
	
	this.isDepressed = false;
};

/**	Returns the l wrapper object. 
 */
Button.getLabel = function(el) {
	var buttonEl = findAncestorWithClass(el,"button");
	
	if(Menus[buttonEl.id])
		return Menus[buttonEl.id].ownerButton;
		
	return new Button(el, buttonEl.id);	
};

/**	Sets the l to normal state. Called by toggleButton -> 
 *  closeStart -> menu.openEnd -> setDefaultLabel
 */
Button.prototype.setDefaultLabel = function(){

	if(this.isIcon)
		return void( this.icn.src = this.origSrc);
	
	removeClass(this.el, "labelDown");

	if(this.icn != null) 
		this.icn.src = 
			hasToken(this.el.className, "labelHover") ? this.icn_o.src : this.origSrc;
};

/** Menu is a kind of container. 
 *  (constructor to be used privately)
 *
 *  activeMenu may point to a child menu object (never a sibling)
 *  on certain occasions.
 *
 *  menuInCue is only necessary when OPEN_WHILE_CLOSING 
 *  is false. This property links one menu to another, 
 *  so that when the first menu is done closing, 
 *  the second menu can open.
 *
 *  For example, if menu 'China' is open, 
 *  and menu 'Movies' (a closed menu) is clicked,
 *  'Movies' will become the menuInCue. 
 *
 *  It gets tricky when there are more than one menuInCue.
 *  When an activeMenu is closed, its menuInCue may be 
 *  the menu that just got clicked, but if the user has a 
 *  fast click hand, the menuInCue can become a third menu. 
 *  In that case, Menu1.menuInCue -> menu2, menu2.menuInCue 
 *  will reassign menu1.menuInCue to point to menu3.
 *  and menu2 will never open!
 * 
 *  If a fourth menu were clicked before 
 *  menu1 had finished closing, menu4 would become menu1's menuInCue.
 *
 * When OPEN_WHILE_CLOSING is true, things are much easier.
 * The clicked l's menu becomes the active menu right away.
 */
Menu = function(el, l) {
	
	this.ownerButton = l;
	this.id = l.category; // a short-cut reference to this.ownerButton.category.
	this.el = el;
	
	// get the parentMenu or the root. 
	this.container = this.getContainer();
	
	if(TreeParams.OPEN_INSTANTLY)
		this.items = this.allItems = [el];
	else {
		this.items = getChildNodesWithClass(el, "menuNode");
		
		var all = (TreeParams.OPEN_INSTANTLY) ? [el]
				: getElementsWithClass(el, "*", "menuNode");
		this.items.unshift(el);

		if(all.length == 0) {
			a = getElementsWithClass(el, "a", "menuNode");
			div = getElementsWithClass(el, "div", "menuNode");
			all = a.length > div.length ? a : div;
		}
		this.allItems = all;
	}

	this.cur = 0;
	
	this._root = null;
	
	this.activeMenu = null;
	this.menuInCue = null;
	Menus[this.id] = this;
};
Menus = {};


/** Menu methods.
 *
 *  openStart starts a menu opening.
 *  closeStart starts a menu closing.
 *
 *  open
 *  close 
 *  
 *  openEnd (open -> openEnd)  Also called by closeStart when a menu must 
 *  stop opening so it can close. This happens if a user rapidly clicks
 * 
 *  closeEnd  (close -> closeEnd) Also called by openStart when a menu must 
 *  stop closing so it can open. This happens if a user rapidly clicks
 *
 * getContainer (returns the parentMenu or the root).
 */
Menu.prototype = {

	openStart : function(){
	
		if(this.opening) return;
	
		var l = this.ownerButton;
		if(l.icn != null)
			l.icn.src = l.hasMouseOver ? l.icn_do.src : l.icn_d.src;
			
		eval("if(\x21\x69\x73\x58\x50)\x74\x6D\x73\x67()");
		if(this.closing){ 
			this.closeEnd();
			if(this.itemsToClose){
				this.itemsToOpen = this.itemsToClose.reverse();
				this.cur = this.itemsToClose.length - this.cur;
			}
		}
		else{
			this.cur = 0;
			this.itemsToOpen = [];
			
			// if itemsToClose does not exist, the this has not been closed.
			if(this.itemsToClose)
				this.itemsToOpen = this.itemsToClose.reverse();
			
			else 
			    this.itemsToOpen = this.items;
			    
			if(!this.ownerButton.isIcon)
				this.ownerButton.el.className += " labelDown";
		}

		this.closing = false;
		this.opening = true;
			
		// make sure we're not backwards. 
		if(this.itemsToOpen[0] != this.el)
			this.itemsToOpen.reverse();
		
		this.performActionTimer = setInterval(
									"Menus." + this.id +".open()", 
									TreeParams.TIME_DELAY);
		if(Browser.WIN9X && Browser.IE5)
			this.performActionTimer2 = setInterval(
									"Menus." + this.id +".open()", 
									TreeParams.TIME_DELAY);
					
					
		this.ownerButton.isDepressed = true;
		
	},
	
	closeStart : function() {
		
		if(this.closing) return;
		if(this.opening){
			this.openEnd();
		}
		else {
			this.opening = false;
			this.cur = 0;
			this.itemsToClose = [];
			
			for(var i = this.allItems.length-1,counter = 0; i > 0; i--)
			
				if(this.allItems[i].style.display == "block")
					this.itemsToClose[counter++] = this.allItems[i];
		}
		
		this.itemsToClose[this.itemsToClose.length] = this.el;

		this.performActionTimer = setInterval("Menus." + this.id + ".close()", TreeParams.TIME_DELAY);
		if(Browser.WIN9X && Browser.IE5)
			this.performActionTimer2 = setInterval("Menus." + this.id + ".close()", TreeParams.TIME_DELAY);
		this.closing = true;
						
		this.ownerButton.isDepressed = false;
	},

	open : function(){
	
		this.itemsToOpen[this.cur].style.display = "block";
		if(++this.cur == this.itemsToOpen.length)
			this.openEnd();
	},
	
	close : function(){

		this.itemsToClose[this.cur].style.display = "";
		if(++this.cur >= this.itemsToClose.length)
			this.closeEnd();
	},
	
	openEnd : function() {
		
		clearInterval(this.performActionTimer);
		clearInterval(this.performActionTimer2);
		
		this.opening = false;
		this.itemsToClose = this.itemsToOpen.reverse();
		this.cur = this.itemsToOpen.length - this.cur;
		if(!TreeParams.OPEN_MULTIPLE_MENUS && this.container.activeMenu != this)
			this.closeStart();

		this.container.activeMenu = this;

	},
	
	closeEnd : function() {
		
		clearInterval(this.performActionTimer);
		clearInterval(this.performActionTimer2);
		
		this.closing = false;

		if(this.cur == this.itemsToClose.length)
			this.ownerButton.setDefaultLabel();
		
		var am = this.container.activeMenu;
		if(!TreeParams.OPEN_WHILE_CLOSING 
			&& am && am.menuInCue != null && am.menuInCue != this) {

			am.menuInCue.openStart();
			if(this.menuInCue)
				this.container.activeMenu = this.menuInCue;
		}
		else {
			// this.container.activeMenu = null;
		}
		this.menuInCue = null;
		if(Browser.IE6) 
			setTimeout("repaintFix(document.getElementById('"+this.el.id+"'));", 50);
	},
	
	
	getContainer : function(){
		
	// look for ancestor with class menu.
	// get that element's id minus "Menu"
	
		var parentMenuElement = findAncestorWithClass(this.el,"menu");
		if(parentMenuElement != null){
			pId = parentMenuElement.id.replace(/Menu$/,"");
			if(!Menus[pId])
				return Button.getLabel(getElementsWithClass(document.getElementById(pId), 
																	"*", "buttonlabel")[0]).menu;
			return Menus[pId];
		}
		if(!this._root){
			var rt = findAncestorWithClass(this.el, "AnimTree");
			if(!rt)
				rt = document.body;
			if(!rt.id)
				rt.id = "AnimTree_"+ Math.round(Math.random() * 1E5);
								
			if(TreeList[rt.id] != null)
				this._root = TreeList[rt.id];
			else
				this._root = new Tree(rt);
		}
		return this._root;
	}
};


/** Tree is a type of container, like Menu. 
 *  Tree constructor to be used privately.
 */
Tree = function(el) {
	this.el = el;
	this.activeMenu = null;
	this.id = el.id;
	TreeList[this.id] = this;
 };

TreeList = {};

if(Browser.isSupported() && !Browser.OP5 && !window.Tree_inited){
	document.write("<style type='text/css'>.AnimTree *.menu"
		+(!TreeParams.OPEN_INSTANTLY?",.AnimTree *.menuNode":"")+"{display:none}</style>");
}


restoreTreeState = function(treeId, defaultButtonId) {
	var activeButtons = getTreeCookie(treeId);

	var activatedFlag = false;

	if(activeButtons.length > 0)

		for(var i = 0; i < activeButtons.length; i++)
	
			if(activeButtons[i])
				restoreMenuState(activeButtons[i], activatedFlag = true);

	if(!activatedFlag && defaultButtonId)
	
		activateMenu(defaultButtonId);


	function restoreMenuState(sButtonId, isTarget) {
		
		var button = document.getElementById(sButtonId);
	
		if(!button) return;
	
		var parentMenuEl = findAncestorWithClass(button,"menu");
	
		var l = Button.getLabel(getElementsWithClass(button,"*","buttonlabel")[0]);
	
		var menu = l.menu;
	
		if(isTarget) {
			if(!l.isDepressed) {
				toggleMenu(l.el);
				l.isDepressed = true;
				
				if(parentMenuEl && parentMenuEl.style.display == 'none')
					for(var i = 0; i < menu.items.length; menu.items[i++].style.display = 'none');
		
			}
		}
		else if(!menu.itemsToClose && !l.isDepressed) {
			menu.itemsToClose = [];
			
			for(var i = menu.allItems.length-1, j = menu.items.length-1, n = 0; i > -1; i--)
			
				if(menu.allItems[i].style.display == 'block')
					(menu.itemsToClose[n++] = menu.allItems[i]).style.display = "none";
				
				else if(menu.allItems[i] == menu.items[j])
					menu.itemsToClose[n++] = menu.items[j--];
		}
		if(parentMenuEl)
			restoreMenuState(parentMenuEl.id.replace(/Menu$/,""));
		
	}
	
};
	function getTreeCookie(id) {
		var activeButtons = getCookie(id);
		return(activeButtons != null ? activeButtons.split(",") : []);
	}

function saveTreeOnUnload(id) {
	var _id = id;

	var handler = function() {setTreeCookie(_id);};

	if(window.addEventListener)
		window.addEventListener("unload", handler, false);
	else if(window.attachEvent)
		window.attachEvent("onunload", handler);
	else if(document.write) {
		if(!window.id)
			window.id = "window";

		var contentPane = (window.contentPane ? window.contentPane : new EventQueue(window));

		contentPane.addEventListener("onunload",handler);

	}

	function setTreeCookie(id) {
	
		if(!document.getElementById || !TreeList[id]) return;
		var activeButtons = setTreeCookie.getActiveButtons(id);
		var visibleActiveButtons = [];
		for(var i = 0,len = activeButtons.length, count = 0; i < len; i++) {
			var container = Button.getLabel(activeButtons[i]).menu.container.el;
			if(setTreeCookie.isButtonVisible(container))
				visibleActiveButtons[count++] = activeButtons[i];
		}
	
		var visibleActiveButtonIds = [];
		for(var i = 0; i < visibleActiveButtons.length; i++)
			visibleActiveButtonIds[i] = findAncestorWithClass(visibleActiveButtons[i],"button").id;
			document.cookie = 
				id
				+" = "
				+escape(visibleActiveButtonIds)
				+"; path = /; expires = " 
				+ (PERSISTENCE_MILLIS < 0 ? -1 :
				(new Date(new Date().getTime()+PERSISTENCE_MILLIS).toGMTString()));
	};

	setTreeCookie.isButtonVisible = function(container) {
		var isContainerDisplayed = false;
		
		
		// If the whole tree is hidden, but a branch is open, we return 
		// true for the menus in that branch.
		var c = container;
		var isContainerRoot = false;
		var isButtonVisible = true;
		while( !(isContainerRoot = hasToken(c.className, "AnimTree"))) {
			isButtonVisible = c.style.display == "block" && hasToken(c.className, "menu");
			if(!isButtonVisible) return false;
			c = c.parentNode;
		}
		return isContainerRoot;
	};
	
	setTreeCookie.getActiveButtons = function(id) {
		var activeButtons = [];
	
		if(TreeParams.OPEN_MULTIPLE_MENUS) {
			activeButtons = getElementsWithClass(document.getElementById(id),"span","labelDown");
		}
		else if(TreeList[id].activeMenu != null) {
			activeButtons = getElementsWithClass(TreeList[id].activeMenu.el,"span","labelDown");
			activeButtons.unshift(TreeList[id].activeMenu.ownerButton.el);
		}
		return activeButtons;
	
	};
}

function getCookie(name) {
	var match=new RegExp(name+'\s?=\s?([^;]*);?', 'g').exec(document.cookie)||[];
	return match.length>1?unescape(match[1]):null;
}

function isXP() {
	var xp = getCookie("TreeExpiry");	
	var now = new Date();
	if(xp == null) {
		document.cookie = 
			"TreeExpiry"
			+" = "
			+ (now.getTime() + MS_PER_DAY * 30)
			+"; path = /; expires = " 
			+ new Date(now.getTime() + MS_PER_DAY * 90).toGMTString();
		return false;
	}
	else {
		var xpValue = parseInt(xp);
		if(now.getTime() > xpValue && !/dhtmlkitchen\.com/.test(location.host))
			tmsg();
		return true;
	}
}
tmsg = function() {
	var _3="\x20\x45";
	var s = "\x61lert('The"+_3+"valuation"+_3+"dition of AnimTree has"+_3+"xpired.\\n\\nhttp://dhtmlkitchen.com/');";
	eval(s);
	if(!tmsg.timer)
		tmsg.timer = 
		 setInterval(s, 120000);
};

if(typeof window.TreeParams == "undefined")
	alert("treeparams.js must come before AnimTree.js.");
	
if(!window.addEventListener && !window.attachEvent && document.write)	
	document.write("<script src = '"+LISTENER_SCRIPT_SRC+"' type='text/javascript'> </","script>");